package test.serverframe.armc.server.util;/**
 * Created by luoxuan on 2018/10/25.
 */

import com.alibaba.fastjson.JSON;
import com.microcore.util.SpringContextUtils;

import test.serverframe.armc.server.manager.domain.ConfigManager;
import test.serverframe.armc.server.manager.service.ConfigManagerService;

import org.apache.commons.lang.StringUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.*;
import org.springframework.http.client.HttpComponentsAsyncClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureCallback;
import org.springframework.web.client.AsyncRestTemplate;
import org.springframework.web.client.RestTemplate;

import java.util.Iterator;

/**
 * @Description
 * @Author LSY
 * @Date 2018/10/25 11:14
 * @ClassName test.serverframe.armc.server.util.RestTemplateUtil rest服务调用工具类
 */
public class RestTemplateUtil {

    private static RestTemplate restTemplate = new RestTemplate(new MicroCoreClientHttpRequestFactory());

    private static AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate();

    private static final Logger logger = LoggerFactory.getLogger(RestTemplateUtil.class);

    /**
     * @Descripttion http调用获取responseEntity
     * @Author LSY
     * @Date 14:55
     * @Param method    请求方法
     * @Param url        请求url
     * @Param queryStr   query参数
     * @Param bodyStr    body参数
     * @Param headerStr  header参数
     * @Return
     **/
    public static String getResponseEntity(HttpMethod method, String url, String queryStr, String bodyStr, String headerStr) throws JSONException {                    //hodyStr 没有数据时，可以为null 或者“{}”
        if (StringUtils.isBlank(queryStr)) {
            queryStr = "{}";
        }
        if (StringUtils.isBlank(bodyStr)) {
            bodyStr = "{}";
        }
        if (StringUtils.isBlank(headerStr)) {
            headerStr = "{}";
        }
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders = getHeader(headerStr, httpHeaders);
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<Object> requestEntity = new HttpEntity(JSON.parse(bodyStr), httpHeaders);
        if (url.indexOf("http://") == -1) {
            url = "http://" + url;
        }
        System.out.println(requestEntity.getHeaders().get("Connection"));
        ResponseEntity<Object> responseEntity = new RestTemplateUtil().getRestTemplate().exchange(url + getParams(queryStr), method, requestEntity, Object.class);
        logger.debug("Send request:" + url);
        return JSON.toJSONString(responseEntity.getBody());
    }

    /**
     * @Descripttion http调用获取responseEntity
     * @Author LSY
     * @Date 14:55
     * @Param method    请求方法
     * @Param url        请求url
     * @Param queryStr   query参数
     * @Param bodyStr    body参数
     * @Param headerStr  header参数
     * @Return
     **/
    public static void getAsyncResponseEntity(HttpMethod method, String url, String queryStr, String bodyStr, String headerStr, ListenableFutureCallback<ResponseEntity<Object>> callback) throws JSONException {                    //hodyStr 没有数据时，可以为null 或者“{}”
        if (method == null) {
            throw new NullPointerException("无效的请求类型");
        }
        if (StringUtils.isBlank(queryStr)) {
            queryStr = "{}";
        }
        if (StringUtils.isBlank(bodyStr)) {
            bodyStr = "{}";
        }
        if (StringUtils.isBlank(headerStr)) {
            headerStr = "{}";
        }
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders = getHeader(headerStr, httpHeaders);
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<Object> requestEntity = new HttpEntity(JSON.parse(bodyStr), httpHeaders);
        if (url.indexOf("http://") == -1) {
            url = "http://" + url;
        }
        System.out.println(requestEntity.getHeaders().get("Connection"));
        ListenableFuture<ResponseEntity<Object>> exchange = new RestTemplateUtil().getAsyncRestTemplate().exchange(url + getParams(queryStr), method, requestEntity, Object.class);
        logger.debug("Send async request:" + url);
        //异步调用后的回调函数
        exchange.addCallback(callback);
    }
    
    private ConfigManagerService configManagerService = SpringContextUtils.getBean("configManagerService", ConfigManagerService.class);
    
    /**
     * 设置同步请求超时时间（连接超时时间、读取数据超时时间、连接池获取连接的超时时间）
	 * @author yegui  
	 * @date 2019年2月21日  
	 * @return RestTemplate
	 */  
	private RestTemplate getRestTemplate() {
		ConfigManager config = configManagerService.selectConfig();
		HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
		httpRequestFactory.setConnectTimeout(config.getHttpConnectTimeout() * 1000);
        httpRequestFactory.setReadTimeout(config.getHttpReadTimeout() * 1000);
        httpRequestFactory.setConnectionRequestTimeout(config.getHttpConnectionRequestTimeout() * 1000);
		return new RestTemplate(httpRequestFactory);
	}
	
	/**
     * 设置异步请求超时时间（连接超时时间、读取数据超时时间、连接池获取连接的超时时间）
	 * @author yegui  
	 * @date 2019年2月21日  
	 * @return AsyncRestTemplate
	 */
	private AsyncRestTemplate getAsyncRestTemplate() {
		ConfigManager config = configManagerService.selectConfig();
		HttpComponentsAsyncClientHttpRequestFactory httpRequestFactory = new HttpComponentsAsyncClientHttpRequestFactory();
		httpRequestFactory.setConnectTimeout(config.getHttpConnectTimeout() * 1000);
        httpRequestFactory.setReadTimeout(config.getHttpReadTimeout() * 1000);
        httpRequestFactory.setConnectionRequestTimeout(config.getHttpConnectionRequestTimeout() * 1000);
		return new AsyncRestTemplate(httpRequestFactory);
	}

    /**
     * @Descripttion header参数添加
     * @Author LSY
     * @Date 14:55
     * @Param jsonStr 待添加的json字符串
     * @Return
     **/
    public static HttpHeaders getHeader(String jsonStr, HttpHeaders httpHeaders) throws JSONException {
        JSONObject jsonObject = new JSONObject(jsonStr);
        Iterator iterator = jsonObject.keys();
        while (iterator.hasNext()) {
            String key = (String) iterator.next();
            String value = jsonObject.getString(key);
            httpHeaders.add(key, value);
        }
        return httpHeaders;
    }


    /**
     * @Descripttion query参数拼接
     * @Author LSY
     * @Date 15:23
     * @Param [jsonStr query参数]
     * @Return
     **/
    public static String getParams(String jsonStr) throws JSONException {
        String params = "";
        StringBuilder stringBuilder = new StringBuilder(params);
        JSONObject jsonObject = new JSONObject(jsonStr);
        Iterator iterator = jsonObject.keys();
        boolean flag = true;
        while (iterator.hasNext()) {
            if (flag) {
                stringBuilder.append("?");
                flag = false;
            } else {
                stringBuilder.append("&");
            }
            String key = (String) iterator.next();
            String value = jsonObject.getString(key);
            stringBuilder.append(key + "=" + value);
        }
        return stringBuilder.toString();
    }

    public static String getCurl(HttpMethod method, String url, String queryStr, String bodyStr, String headerStr) throws JSONException {
        if (StringUtils.isBlank(queryStr)) {
            queryStr = "{}";
        }
        if (StringUtils.isBlank(bodyStr)) {
            bodyStr = "{}";
        }
        if (StringUtils.isBlank(headerStr)) {
            headerStr = "{}";
        }

        StringBuilder curl=new StringBuilder();
        curl.append("curl -X ");
        curl.append(method.toString());
        curl.append(" --header \"Content-Type: application/json\" --header \"Accept: */*\"");

        JSONObject jsonObject = new JSONObject(headerStr);
        Iterator iterator = jsonObject.keys();
        while (iterator.hasNext()) {
            String key = (String) iterator.next();
            String value = jsonObject.getString(key);
            curl.append(" --header \""+key+":"+value+"\"");
        }
        curl.append(" -d \""+bodyStr+"\"");
        if (url.indexOf("http://") == -1) {
            url = " http://" + url;
        }
        curl.append("\""+url+getParams(queryStr)+"\"");

        return curl.toString();
    }

    public static String getUrl(String url,String queryStr) throws JSONException {
        if (StringUtils.isBlank(queryStr)) {
            queryStr = "{}";
        }
        if (url.indexOf("http://") == -1) {
            url = "http://" + url;
        }
        return url+getParams(queryStr);
    }
}
